﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace GibbsLDASharp.LDA
{
    public class CmdLineParser
    {
        private Dictionary<string, string> commandDict = new Dictionary<string, string>();
        ICommandOption options;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="options">用来保存读取出的参数</param>
        public CmdLineParser(ICommandOption options)
        {
            this.options = options;

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="argvs">含有参数的字符串数组</param>
        public void ParseCommandLine(string[] argvs)
        {
            OptionAttribute optAttribSample = new OptionAttribute();//这个是给后面的GetCustomAttribute作为参数
            OptionAttribute optAttrib;

            //将参数读取到一个字典中来，每个参数的名字前需要有“-”,如-est等。不带“-”的字符串作为前一项的值读入
            for (int i = 0; i < argvs.Length; i++)
            {
                if (i + 1 < argvs.Length)
                {
                    if (argvs[i][0] == '-' && argvs[i + 1][0] != '-')
                    {
                        commandDict.Add(argvs[i], argvs[i + 1]);
                        i++;
                        continue;
                    }
                }
                //这里判断是不是有重复的参数，重复了以第一个出现的为准
                if (!commandDict.Contains(new KeyValuePair<string, string>(argvs[i], "")))
                    commandDict.Add(argvs[i], "");

            }
            FieldInfo[] fieldInfos = options.GetType().GetFields(); //通过反射获取所有的字段
            foreach (FieldInfo fieldInfo in fieldInfos)
            {
                optAttrib = fieldInfo.GetCustomAttribute(optAttribSample.GetType()) as OptionAttribute; //获取每个字段的自定义特性，这里获取的是我们前面定义的OptionAttribute
                string newType = optAttrib.OptionType.ToLower();//类型名字，都转成小写统一比较
                string value;
                switch (newType.ToLower())//这里判断类型，然后进行相应的转换
                {
                    case "bool":

                        if (!commandDict.TryGetValue(optAttrib.Command, out value))
                        {
                            if (fieldInfo.GetValue(options) == null)
                                fieldInfo.SetValue(options, false);
                            continue;
                        }
                        else
                            fieldInfo.SetValue(options, true);
                        break;
                    case "string":
                        if (!commandDict.TryGetValue(optAttrib.Command, out value))
                        {
                            if (fieldInfo.GetValue(options) == null)
                                fieldInfo.SetValue(options, null);
                            continue;
                        }
                        else
                            fieldInfo.SetValue(options, value);
                        break;
                    case "double":
                        if (!commandDict.TryGetValue(optAttrib.Command, out value))
                        {
                            if (fieldInfo.GetValue(options) == null)
                                fieldInfo.SetValue(options, null);
                            continue;
                        }
                        else
                            fieldInfo.SetValue(options, double.Parse(value));
                        break;
                    case "float":
                        if (!commandDict.TryGetValue(optAttrib.Command, out value))
                        {
                            if (fieldInfo.GetValue(options) == null)
                                fieldInfo.SetValue(options, null);
                            continue;
                        }
                        else
                            fieldInfo.SetValue(options, float.Parse(value));
                        break;
                    case "int":
                        if (!commandDict.TryGetValue(optAttrib.Command, out value))
                        {
                            if (fieldInfo.GetValue(options) == null)
                                fieldInfo.SetValue(options, null);
                            continue;
                        }
                        else
                            fieldInfo.SetValue(options, int.Parse(value));
                        break;

                }
                //fieldInfo.SetValue(options,
            }
        }

        public void ShowUsages()
        {
            OptionAttribute optAttribSample = new OptionAttribute();//这个是给后面的GetCustomAttribute作为参数
            OptionAttribute optAttrib;

            FieldInfo[] fieldInfos = options.GetType().GetFields(); //通过反射获取所有的字段
            foreach (FieldInfo fieldInfo in fieldInfos)
            {
                optAttrib = fieldInfo.GetCustomAttribute(optAttribSample.GetType()) as OptionAttribute; //获取每个字段的自定义特性，这里获取的是我们前面定义的OptionAttribute
                string newType = optAttrib.OptionType.ToLower();//类型名字，都转成小写统一比较
                Console.WriteLine(string.Format("{0}<{1}>:\t\t\t{2}\n",optAttrib.Command,optAttrib.OptionType,optAttrib.Description));
            }
        }
    }
    //[AttributeUsage(AttributeTargets.Field, Inherited = false)]
    public class OptionAttribute : Attribute
    {
        public OptionAttribute()
        {
            this.command = string.Empty;
            this.description = string.Empty;
            this.optionType = null;
        }

        public OptionAttribute(string Cmd, string TypeName, string Description)
        {
            this.command = Cmd;
            this.description = Description;
            this.optionType = TypeName;
        }

        protected string optionType;
        public string OptionType
        {
            set
            {
                this.optionType = value;
            }
            get
            {
                return this.optionType;
            }
        }
        protected string command;
        public string Command
        {
            set
            {
                this.command = value;
            }
            get
            {
                return this.command;
            }
        }

        protected string description;
        public string Description
        {
            set
            {
                this.description = value;
            }
            get
            {
                return this.description;
            }
        }
    }
    public class ICommandOption
    {

    }
}
